/*
 * @Author: ZhanXie
 * @Date: 2020-02-28 10:20:44
 * @LastEditors: ZhanXie
 * @LastEditTime: 2020-03-09 10:45:41
 * @Description: 头信息处理
 * @FilePath: /projectStudy/ts-axios/src/helpers/headers.ts
 */
import { isPlainObject, deepMerge } from './util'
import { Method } from '../types'

/**
 * 格式化头信息
 * 忽略特定头信息的大小写, 重新赋予我们需要的 key 值
 * @param headers 要设置的头信息
 * @param normalizeName 要同步的头信息 key 值
 */
function normalizeHeaderName(headers: any, normalizeName: string): void {
  if (!headers) {
    return
  }
  Object.keys(headers).forEach(name => {
    if (name !== normalizeName && name.toLocaleUpperCase() === normalizeName.toLocaleUpperCase()) {
      headers[normalizeName] = headers[name]
      delete headers[name]
    }
  })
}

/**
 * 处理请求头信息
 * 如果 data 是 object 则给 content-type 设置默认值 'application/json;charset=utf-8'
 * @param headers 要设置的头信息
 * @param data 发送给后台的 data 数据
 */
export function processHeaders(headers: any, data: any): any {
  normalizeHeaderName(headers, 'Content-Type')
  if (isPlainObject(data)) {
    if (headers && !headers['Content-Type']) {
      headers['Content-Type'] = 'application/json;charset=utf-8'
    }
  }
  return headers
}

export function parseHeaders(headers: string): any {
  let parsers = Object.create(null)
  if (!headers) {
    return
  }
  headers.split('\r\n').forEach(line => {
    let [key, val] = line.split(':')
    key = key.trim().toLocaleLowerCase()
    if (!key) {
      return
    }
    if (val) {
      val = val.trim()
    }
    parsers[key] = val
  })

  return parsers
}

/**
 * 处理 headers
 * 把 `common`、`post` 的属性拷贝到 `headers` 这一级，然后再把 `common`、`post` 这些属性删掉。
 * headers: {
 *  common: {
 *    Accept: 'application/json, text/plain'
 *  },
 *  post: {
 *    'Content-Type':'application/x-www-form-urlencoded'
 *  }
 * }
 * =>
 * headers: {
 *  Accept: 'application/json, text/plain',
 *  'Content-Type': 'application/x-www-form-urlencoded'
 * }
 * @param headers
 * @param method
 *
 */
export function flattenHeaders(headers: any, method: Method) {
  if (!headers) {
    return headers
  }
  headers = deepMerge(headers.common || {}, headers[method] || {}, headers)
  const methodsToDelete = ['delete', 'get', 'head', 'options', 'post', 'put', 'patch', 'common']
  methodsToDelete.forEach(method => {
    delete headers[method]
  })
  return headers
}
